﻿using Engine.Entities.Character;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace Assets.Engine.AI.GeneticAlgorithm
{
    class Genetic
    {
        private FrenzyPeopleController peopleCtrl { get; set; }
        
        public Genetic(FrenzyPeopleController peopleCtrl)
        {
            this.peopleCtrl = peopleCtrl;
        }

        public SteveModel Couple(SteveModel A, SteveModel B, GeneticVariables variable)
        {
            //con undefined assegno un sesso casuale
            SteveModel newmodel = new SteveModel(GenderEnum.Undefined);

            CrossOver(A, B, ref newmodel, variable);

            Mutation(ref newmodel, variable);

            //Debug.Log("MAX: " + FrenzyPeopleController.GetMaxSkill(SkillsEnum.Intelligence) + " # " +
            //                    FrenzyPeopleController.GetMaxSkill(SkillsEnum.Resistance) + " # " +
            //                    FrenzyPeopleController.GetMaxSkill(SkillsEnum.Strenght) + " # " +
            //                    FrenzyPeopleController.GetMaxSkill(SkillsEnum.Agility) + " # " +
            //                    FrenzyPeopleController.GetMaxSkill(SkillsEnum.Charm) + " # " +
            //                    FrenzyPeopleController.GetMaxSkill(SkillsEnum.Appeal) + " # ");

            return newmodel;
        }

        /// <summary>
        ///     Applica l'algoritmo del crossover sul nuovo perrsonaggio creato
        /// </summary>
        /// <param name="A"> Madre </param>
        /// <param name="B"> Padre </param>
        /// <param name="character">
        ///     Nuovo personaggio creato
        /// </param>
        /// <param name="variable">
        ///     Variabili dell'algoritmo genetico
        /// </param>

        private void CrossOver(SteveModel A, SteveModel B,
                                ref SteveModel character, 
                                GeneticVariables variable)
        {

            // mixingRatio = 0    A -> character (male)
            // mixingRatio = 1    B -> character (female)

            float mixingRatio = variable.MixingRatio;
            float dice;
            int valueSkill;

            string debug = "Mixingratio: " + mixingRatio + " Dice crossover: ";
            for (int i = 0; i < Skills.NUMBER_OF_SKILLS; i++)
            {
                SkillsEnum mixingSkill = Skills.GetTypeSkill(i);
                dice = UnityEngine.Random.value;

                debug += dice + " ";

                if (dice > mixingRatio)
                    valueSkill = A.Skills.GetValue(mixingSkill);    //mother
                else
                    valueSkill = B.Skills.GetValue(mixingSkill);    //father

                peopleCtrl.SetSkill(mixingSkill, valueSkill, character.Skills);
            }

            //Debug.Log(debug);
        }

        /// <summary>
        ///     Applica la mutazione al nuovo personaggio creato
        /// </summary>
        /// <param name="newCharacter">
        ///     Nuovo personaggio
        /// </param>
        /// <param name="variable">
        ///     Variabili genetiche
        /// </param>

        private void Mutation(ref SteveModel newCharacter, GeneticVariables variable)
        {
            float dice;
            float percentage = variable.PercentageMutation;

            string debug_dice = "Percentage: " + percentage + " ";
            string debug_mutation = "ValueMutation[" + variable.MinMutation + " " + variable.MaxMutation + "]: ";
            string debug_value = "ValueSkill: ";

            for (int i = 0; i < Skills.NUMBER_OF_SKILLS; i++)
            {
                SkillsEnum skill = Skills.GetTypeSkill(i);
                dice = UnityEngine.Random.value;

                debug_dice += dice + " ";

                if (dice < percentage)
                {
                    int value = newCharacter.Skills.GetValue(skill);
                    int mutation = UnityEngine.Random.Range(variable.MinMutation, variable.MaxMutation + 1);

                    debug_mutation += mutation + " # ";
                    debug_value += value;

                    if (mutation != 0)
                        peopleCtrl.SetSkill(skill, mutation + value, newCharacter.Skills);
                }
            }

            //Debug.Log(debug_dice);
            Debug.Log(debug_mutation);
        }

        
    }
}
